package org.dizena.common.db;

import org.dizena.utils.ObjUtil;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public abstract class CommonRepository<T> implements CommonDao<T>
{

    public Query idQuery(String id)
    {
        return new Query(Criteria.where("id").is(id));
    }

    public Query kvQuery(String key, Object val)
    {
        return new Query(Criteria.where(key).is(val));
    }

    public Query kvQuery(String[] keys, Object[] vales)
    {
        if (keys != null && keys.length > 0 && keys.length == vales.length)
        {
            Criteria c = Criteria.where(keys[0]).is(vales[0]);
            for (int i = 1; i < vales.length; i++)
            {
                c = c.and(keys[i]).is(vales[i]);
            }
            return new Query(c);
        }
        return new Query();
    }

    public Update mongoUpdate(Object obj)
    {
        Update update = new Update();
        Map<String, Object> map = ObjUtil.beanAttrToMapKV(obj);
        for (Entry<String, Object> e : map.entrySet())
        {
            if ("id".equals(e.getKey()))
            {
                continue;
            }
            update.set(e.getKey(), e.getValue());
        }
        return update;
    }

    public Query pageQuery(ByPageQuery<T> pageQuery)
    {
        Query query = countQuery(pageQuery);
        if (pageQuery != null)
        {
            if (pageQuery.getSkip() != 0)
            {
                query.skip(pageQuery.getSkip());
            }
            if (pageQuery.getLimit() != 0)
            {
                query.limit(pageQuery.getLimit());
            }
            if (pageQuery.getDirection() != null && pageQuery.getSortField() != null)
            {
                Sort sort = Sort.by(Sort.Direction.fromString(pageQuery.getDirection()), pageQuery.getSortField());
                query.with(sort);
            }
        }
        return query;
    }

    public Query countQuery(ByPageQuery<T> pageQuery)
    {
        if (pageQuery != null)
        {
            return map2QueryLike(pageQuery.getParam(), pageQuery.getSearchField());
        }
        return new Query();
    }

    private Query map2QueryLike(Map<String, Object> map, String searchField)
    {
        Criteria criteria = null;
        if (map != null && map.size() > 0)
        {
            Set<Entry<String, Object>> sets = map.entrySet();
            int i = 0;
            for (Entry<String, Object> entry : sets)
            {
                String key = entry.getKey();
                Object val = entry.getValue();
                if (key.equals(searchField))
                {
                    String seal = (String) val;
                    if (i == 0)
                    {
                        criteria = Criteria.where(searchField).regex(seal);
                    }
                    else
                    {
                        criteria = criteria.and(searchField).regex(seal);
                    }
                }
                else
                {
                    // other
                    if (i == 0)
                    {
                        criteria = Criteria.where(key).is(val);
                    }
                    else
                    {
                        criteria = criteria.and(key).is(val);
                    }
                }

                i++;
            }
        }
        Query query = new Query();
        if (criteria != null)
        {
            query = new Query(criteria);
        }
        return query;
    }

}
